<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/12/27 0027
 * Time: 下午 2:25
 */

namespace common\models\Admin;


use common\components\DataHelper;
use common\models\AgentInfo\AgentInfo;
use common\models\RegionManagerInfo\RegionManagerInfo;
use yii\db\ActiveQuery;
use yii\helpers\ArrayHelper;

class Admin extends AdminBase
{
    private static $CURRENT_USER;

    const DEFAULT_ROOT_ID = 1;

    const TYPE_ADMIN = 0;
    const TYPE_AGENT = 2;
    const TYPE_REGION_MANAGER = 1;

    const TOKEN_NAME = '_token';
    const REFRESH_TOKEN_NAME = '_refresh_token';
    const TOKEN_STATUS_ALLOW = 1;
    const TOKEN_STATUS_DISABLED = 2;

    const LOGIN_SESSION_NAME = 'admin';

    /**
     * token过期时间
     */
    const TOKEN_EXPIRE = 30;

    const SCENARIO_OPERATE = "operate";

    public $userInfo;


    public static function getTypeMap($key = "ALL", $default = false)
    {
        $ret = [
            self::TYPE_ADMIN => "管理员",
            self::TYPE_REGION_MANAGER => "区域总经理",
            self::TYPE_AGENT => "代理商"
        ];
        if ( $key === "ALL" ) {
            return $ret;
        }
        return ArrayHelper::getValue($ret, $key, $default);
    }

    /**
     * 创建检索条件
     * @param ActiveQuery $query
     * @param $params
     */
    public static function createSearchCondition(ActiveQuery $query, $params)
    {
        if ( @$params["key"] ) {
            $params[$params["key"]] = @$params["val"];/*
            switch ( $params["key"] ) {
                case "agent_name":
                    $params["agent_name"] = @$params["val"];
                    break;
                case "manager_name":
                    $params["manager_name"] = @$params["val"];
                    break;
                case "agent_level":
                    $params["agent_level"] = @$params["val"];
                    break;
                case "username":
                    $params["username"] = @$params["val"];
                    break;
            }*/
        }

        if ( @$params["agent_name"] ) {
            $agentIds = AgentInfo::find()->select("uid")->andWhere([
                "like",
                "name",
                $params["agent_name"]
            ])->asArray()->all();
            $query->andWhere([
                "id" => array_column($agentIds, "uid")
            ]);
        }

        if ( @$params["manager_name"] ) {
            $agentIds = RegionManagerInfo::find()->select(AgentInfo::tableName().".uid")->andWhere([
                "like",
                RegionManagerInfo::tableName().".name",
                $params["manager_name"]
            ])->leftJoin(AgentInfo::tableName(), "parent_manager=".RegionManagerInfo::tableName().".uid")->asArray()->all();
            $query->andWhere([
                "id" => array_column($agentIds, "uid")
            ]);
        }

        if ( @$params["agent_level"] ) {
            if ( $params["agent_level"] == "top" ) {
                $agentIds = AgentInfo::find()->select("uid")->where([
                    "parent_agent" => 0
                ])->asArray()->all();
            } else {
                $agentIds = AgentInfo::find()->select("uid")->where("parent_agent>0")->asArray()->all();
            }
            $query->andWhere([
                "id" => array_column($agentIds, "uid")
            ]);
        }

        if ( @$params["username"] ) {
            $query->andWhere('locate(:username, username)', [':username'=>trim($params['username'])]);
        }

        if ( @$params["time_end"] && ($params["time_end"] = strtotime($params["time_end"])) ) {
            $query->andWhere("created_time <= :end", [
                ":end" => $params["time_end"]
            ]);
        }

        if ( !DataHelper::isEmpty(@$params["status"]) ) {
            $query->andWhere([
                "status" => $params["status"]
            ]);
        }
        return ;
    }

    public static function getAgentIdsByCurrentManager()
    {
        $agentIds = AgentInfo::find()->select("uid")->where([
            "parent_manager" => self::getCurrentUser("id")
        ])->asArray()->all();
        return array_column($agentIds, "uid");
    }

    public static function getAgentIdsByCurrentAgent()
    {
        $agentIds = AgentInfo::find()->select("uid")->where([
            "parent_agent" => self::getCurrentUser("id")
        ])->asArray()->all();
        return array_column($agentIds, "uid");
    }

    /**
     * @param array $params
     * params = [
     *      username => "",
     *      password => "",
     *      userInfo => [...],
     * ];
     * @param $type
     * @param int $id
     * @return bool
     */
    public static function setUserAccount(array $params, $type, $id = 0)
    {
        $transaction = self::getDb()->beginTransaction();
        if ( $id ) {
            $user = Admin::findOne([
                "id" => $id,
                "type" => $type
            ]);
            if ( !$user ) {
                self::error("未知的用户");
                return false;
            }
            $user->scenario = self::SCENARIO_OPERATE;
            $user->attributes = $params;
            if ( !$user->password ) {
                $user->password = $user->oldAttributes["password"];
            }
            if ( !$user->save() ) {
                self::error($user->getFirstErrorToStr());
                $transaction->rollBack();
                return false;
            }
        } else {
            $user = self::createAccount(@$params["username"], @$params["password"], $type);
            unset($params["username"], $params["password"]);
            if ( !$user ) {
                $transaction->rollBack();
                return false;
            }
        }

        if ( $type == self::TYPE_REGION_MANAGER ) {
            $userInfo = $id ? RegionManagerInfo::findOne([
                "uid" => $user->id
            ]) : new RegionManagerInfo();
            if ( !$userInfo ) {
                $userInfo = new RegionManagerInfo();
            }
            $userInfo->attributes = $params["userInfo"];
            @$params["rev_price_image"] && $userInfo->rev_price_image = $params["rev_price_image"];
        } elseif ( $type == self::TYPE_AGENT ) {
            $userInfo = $id ? AgentInfo::findOne([
                "uid" => $user->id
            ]) : new AgentInfo();
            if ( !$userInfo ) {
                $userInfo = new AgentInfo();
            }
            $userInfo->attributes = $params["userInfo"];
            @$params["rev_price_image"] && $userInfo->rev_price_image = $params["rev_price_image"];
            if ( $userInfo->getIsNewRecord() || $userInfo->isAttributeChanged("parent_agent") ) {
                if ( $userInfo->parent_agent != 0 ) {
                    if ( $userInfo->parent_agent == $user->id ) {
                        self::error("不能选择自己作为上级代理");
                        return false;
                    }
                    $ret = AgentInfo::find()->select(["uid", "parent_manager"])->where([
                        "uid" => $userInfo->parent_agent,
                    ])->one();
                    if ( !$ret ) {
                        self::error("无效的代理商");
                        $transaction->rollBack();
                        return false;
                    }
                    if ( $ret["parent_agent"] != 0 ) {
                        $transaction->rollBack();
                        self::error("不是顶级代理");
                        return false;
                    }
                    $userInfo->parent_manager = $ret["parent_manager"];
                }
            }
            $userInfo->parent_agent = intval($userInfo->parent_agent);
            //顶级代理才检查区域经理
            if ( $userInfo->parent_agent == 0 ) {
                if ( $userInfo->getIsNewRecord() || $userInfo->isAttributeChanged("parent_manager") ) {
                    $ret = self::find()->select("id")->where([
                        "id" => $userInfo->parent_manager,
                        "type" => self::TYPE_REGION_MANAGER
                    ])->one();
                    if ( !$ret ) {
                        $transaction->rollBack();
                        self::error("无效的区域经理");
                        return false;
                    }
                    //这里是有修改区域经理的情况

                    //这里需要更新子代理的区域经理
                    $ret = AgentInfo::updateAll([
                        "parent_manager" => $userInfo->parent_manager,
                    ], [
                        "parent_agent" => $userInfo->uid
                    ]);
                    if ( $ret === false ) {
                        self::error("子代理区域经理更改失败");
                        return false;
                    }
                }

                if ( !$userInfo->parent_manager ) {
                    self::error("请选择区域经理");
                    return false;
                }
            }
        }
        if ( !isset($userInfo) ) {
            $transaction->commit();
            return true;
        }
        $userInfo->uid = $user->id;
        if ( $userInfo->save() ) {
            $user->userInfo = $userInfo;
            $transaction->commit();
            return $user;
        }

        self::error($userInfo->getFirstErrorToStr());
        $transaction->rollBack();
        return false;

    }

    public static function createAccount($username, $password, $type)
    {
        $user = new Admin();
        $user->type = $type;
        if ( !self::getTypeMap($user->type) ) {
            self::error("无效的类型");
            return false;
        }
        $user->username = $username;
        $user->password = $password;
        $user->status = Admin::STATUS_YES;
        $user->created_time = DataHelper::date();
        if ( $user->insert() ) {
            return $user;
        }
        self::error($user->getFirstErrorToStr());
        return false;
    }

    public static function isAdminCurrent()
    {
        return self::getCurrentUser("type") == self::TYPE_ADMIN;
    }

    public static function isRegionManagerCurrent()
    {
        return self::getCurrentUser("type") == self::TYPE_REGION_MANAGER;
    }

    public static function isAgentCurrent()
    {
        return self::getCurrentUser("type") == self::TYPE_AGENT;
    }


    public function beforeValidate()
    {
        if ( !$this->salt ) {
            $this->salt = Admin::generateSalt();
        }
        return parent::beforeValidate(); // TODO: Change the autogenerated stub
    }

    public function beforeSave($insert)
    {
        if ( $insert || $this->isAttributeChanged("password") ) {
            !$this->salt && $this->salt = Admin::generateSalt();
            $this->password = Admin::getPassword($this->password, $this->salt);
        }
        return parent::beforeSave($insert); // TODO: Change the autogenerated stub
    }

    public function changeStatus($status)
    {
        $this->status = $status;
        if ( !self::getStatusMap($this->status) ) {
            $this->addError("status", "无效的状态");
            return false;
        }
        return $this->save(0);
    }

    public function isAgent()
    {
        return $this->type == self::TYPE_AGENT;
    }

    public function isRegionManager()
    {
        return $this->type == self::TYPE_REGION_MANAGER;
    }

    public function isAdmin()
    {
        return $this->type == self::TYPE_ADMIN;
    }

    public function isTopAgent()
    {
        if ( $this->isAgent() ) {
            $ret = AgentInfo::find()->select("uid")->where([
                "uid" => $this->id,
                "parent_agent" => 0
            ]);
            return $ret ? true : false;
        }
        return false;
    }

    public static function isTopAgentCurrent()
    {
        if ( self::isAgentCurrent() ) {
            $ret = AgentInfo::find()->select("uid")->where([
                "uid" => self::getCurrentUser("id"),
                "parent_agent" => 0
            ])->one();
            return $ret ? true : false;
        }
        return false;
    }

    public function isRoot()
    {
        return $this->id == self::DEFAULT_ROOT_ID;
    }

    public function scenarios()
    {
        return array_merge(parent::scenarios(), [
            self::SCENARIO_OPERATE => [
                "username",
                "password",
                "status",
            ]
        ]); // TODO: Change the autogenerated stub
    }

    public function getAgentInfo()
    {
        return $this->hasOne(AgentInfo::class, [
            "uid" => "id"
        ]);
    }

    public function getRegionManagerInfo()
    {
        return $this->hasOne(RegionManagerInfo::class, [
            "uid" => "id"
        ]);
    }

    /**
     * @param $username
     * @param $password
     * @param bool $isSession session登陆 这里避免与api端登陆冲突 所以web端用session登陆 不影响api的token
     * @return bool
     */
    public function login($username, $password, $isSession = false)
    {
        $adminQuery = $this->getRowByCondition([
            'username'=>$username
        ], true);

        if ( !$adminQuery ) {
            $this->addError('username', '未知的账户');
            return false;
        }

        if ( self::getPassword($password, $adminQuery->salt) != $adminQuery->password ) {
            $this->addError('username', '错误的用户名或密码');
            return false;
        }

        if ( $adminQuery->status != self::STATUS_YES ) {
            $this->addError('username', '该账户已被禁用');
            return false;
        }

        if ( $isSession ) {
            $adminQuery->login_time = DataHelper::date();
            $adminQuery->login_ip = ip2long(\Yii::$app->request->userIP);
            $adminQuery->update(0);
            \Yii::$app->getSession()->set(self::LOGIN_SESSION_NAME, $adminQuery->toArray());
            return true;
        }

        $adminQuery->token = self::generateToken();
        $adminQuery->refresh_token = md5($adminQuery->token . microtime(true));
        $adminQuery->token_expire = strtotime("+".self::TOKEN_EXPIRE . 'days', time());
        $adminQuery->token_expire = DataHelper::date($adminQuery->token_expire);

        $adminQuery->token_status = self::TOKEN_STATUS_ALLOW;
        $adminQuery->login_time = DataHelper::date();
        $adminQuery->login_ip = ip2long(\Yii::$app->request->userIP);
        $adminQuery->update(0);

        self::$CURRENT_USER = $adminQuery;

        return true;
    }

    /**
     * 检查登陆
     * @param bool $isSession 是否是session方式登陆检查
     * @return bool
     */
    public function checkLogin($isSession = false)
    {
        if ( self::$CURRENT_USER && isset(self::$CURRENT_USER['id']) ) {
            return true;
        }

        if ( $isSession ) {
            self::$CURRENT_USER = \Yii::$app->getSession()->get(self::LOGIN_SESSION_NAME);
            if ( !self::$CURRENT_USER ) {
                $this->addError('session', '账户未登录');
                return false;
            } else {
                return true;
            }
        }

        $request = \Yii::$app->request;
        $request_params = $request = array_merge($request->get(), $request->getBodyParams());
        $token = isset($request_params[self::TOKEN_NAME]) ? $request_params[self::TOKEN_NAME] : \Yii::$app->request->cookies->get(self::TOKEN_NAME);

        if ( !$token ) {
            $this->addError('token', '无效的token');
            return false;
        }

        $query = $this->getRowByPk([
            'token'=>$token
        ]);

        if ( !$query ) {
            $this->addError('token', '账户未登录');
            return false;
        }

        if ( $query->token_status != self::TOKEN_STATUS_ALLOW ) {
            $this->addError('登陆已失效， 请重新登陆');
            return false;
        }

        if ( strtotime($query->token_expire) <= time() ) {
            $this->addError('token', '登录已超时，请重新登陆');
            return false;
        }

        if ( $query->status != self::STATUS_YES ) {
            $this->addError('username', '该账户已被禁用');
            return false;
        }

        self::$CURRENT_USER = $query;

        return true;
    }

    public static function getCurrentUser($key = 'ALL', $isSession = false)
    {
        //如果不存在userInfo则自动检查一次登录获取userInfo
        if ( !self::$CURRENT_USER ) {
            $self = new self();
            //这里优先检测isSession选择的方式 然后检测token方式
            if ( !$self->checkLogin($isSession) ) {
                if ( !$self->checkLogin(!$isSession) ) {
                    return false;
                }
            }
        }

        if ( $key === 'ALL' ) return self::$CURRENT_USER;

        return isset(self::$CURRENT_USER[$key]) ? self::$CURRENT_USER[$key] : false;
    }

    /**
     * 生成盐值
     * @param string $prefix
     * @return string
     */
    public static function generateSalt($prefix='')
    {
        return uniqid($prefix);
    }

    /**
     * 获取加盐后的密码
     * @param $password
     * @param $salt
     * @return string
     */
    public static function getPassword($password, $salt)
    {
        return md5(sprintf('_%s_%s_', $password, $salt));
    }

    /**
     * 生成一个token值
     * @return mixed
     */
    public static function generateToken()
    {
        return md5(uniqid(null, true));
    }

    public static function getRootIds()
    {
        return [1];
    }

    /**
     * 退出登陆
     * @return bool|false|int
     */
    public static function logout()
    {
        \Yii::$app->getSession()->open();
        @session_unset();
        @session_destroy();
        return ;
    }
}